package com.modules.websocket;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
 
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import cn.hutool.json.JSONObject;
 

@ServerEndpoint("/webSocket/{type}/{uuid}")  
public class WebSocket { 
	
    private static int onlineCount = 0; // 统计在线人数的
    private static Map<String, WebSocket> loginMap = new ConcurrentHashMap<String, WebSocket>(); // 饿汉式
    private static List<Map<String, WebSocket>> clients = null; // 懒汉式
    public Session session; 
    public String userName; 
    public String uuid; 
    public static long timeCount = 0;
    
   /**
    * 打开连接
    * @param type
    * @param username
    * @param session
    * @throws IOException
    */
    @OnOpen 
    public void onOpen(@PathParam("type") String type,@PathParam("uuid") String uuid, Session session) throws IOException {
    	
    	this.userName = type;
        this.uuid = uuid;
        this.session = session;
        
        if(type != null) {
        	 if(type.equals("login")) {// 登录
        		 loginMap.put(uuid, this);
             }else{
            	 if(clients == null) {// 大数据
                  	synchronized (WebSocket.class) {
      					if(clients == null) {
      						clients = new ArrayList<Map<String, WebSocket>>();
      					}
      				}
            	 }
  	        	 Map<String, WebSocket> clien = new ConcurrentHashMap<String, WebSocket>(); 
  	             clien.put(uuid, this);
  	             clients.add(clien);
             }
        }
        //addOnlineCount();//本来用统计在线人数的
    }
    
   /**
    * 删除
    * @throws IOException
    */
    @OnClose 
    public void onClose() throws IOException { 
    	if(userName != null && userName.equals("login")) {// 登录
    		if(loginMap != null) {
        		loginMap.remove(uuid); 
        	}
    	}else {
    		if(clients != null) {
        		for(int i=0; i< clients.size(); i++) { // 大数据
            		Map<String, WebSocket> clien = clients.get(i);
            		for (WebSocket item : clien.values()) {
            			if(item.session.equals(session))
                			clients.remove(i);
            		}
            	}
        	}
    	}
        //subOnlineCount(); //本来用统计在线人数的
    }
    
    /**
     * 错误信息
     */
     @OnError 
     public void onError(Session session, Throwable error) {
         error.printStackTrace();
     }
     
    /**
     * 接收数据
     * @param jsonTo
     * @throws IOException
     */
    @OnMessage 
    public static void onMessage(String message) throws IOException {
        JSONObject jsonTo = new JSONObject(message);
        String mes = (String) jsonTo.get("message");
        String type = (String) jsonTo.get("type");
        String to = (String) jsonTo.get("To");
        if(type != null) {
        	if(type.equals("login")){// 登录
            	sendMessageLoginTo(mes, to);
            }else if(type.equals("data")) {// 大数据
        		//sendMessage(mes, to);
            	sendMessageAll(mes);
            }
        }
    } 
    
    /**
	  * 发给指定-登录
	  * @param message
	  * @param To
	  * @param mark
	  * @throws IOException
	*/
    public static void sendMessageLoginTo(String message, String To) throws IOException { 
    	//session.getBasicRemote().sendText(message); // 同步
    	//session.getAsyncRemote().sendText(message); // 异步
    	if (loginMap != null) {
    		for (WebSocket item : loginMap.values()) {
    			if (item.uuid.equals(To) )
    				item.session.getAsyncRemote().sendText(message); 
    		} 
    	}
	}
    
    /**
     * 发给指定-大数据
     * @param message
     * @param To
     * @param mark
     * @throws IOException
     */
     public static void sendMessage(String message, String to) throws IOException { 
     	if (clients != null) {	// 大数据
     		for(int i=0; i< clients.size(); i++) {// 这里（循环中套了个循环判断，用了线程加自带的异步推送）
     			new WebSocketThread(i,clients, to, message).start();
     		}
     	}
     	// 说明：如果多个消息推送使用同一个session推送消息，socket多线程冲突
     	// 报错：webSocket多线程推送出错，报错信息为The remote endpoint was in state [TEXT_PARTIAL_WRITING]
     	// 建议使用：Thread.sleep(100); 根据同一个session判断（自己写咯）
	}
     
   /**
    * 发给指定-大数据2
    * @param message
    * @param To
    * @param mark
    * @throws IOException
    */
    public static void sendMessageTo(String message, String to) throws IOException { 
    	if (clients != null) {	// 大数据
    		for(int i=0; i< clients.size(); i++) {
    			Map<String, WebSocket> clien = clients.get(i);
    			for (WebSocket item : clien.values()) {
    				if (item.uuid.equals(to) )
    					item.session.getAsyncRemote().sendText(message); 
    			}
    		}
		}
    }
    
    /**
     * 发给全部 -大数据
     * @param message
     * @throws IOException
     */
    public static void sendMessageAll(String message) throws IOException { 
    	for(int i=0; i< clients.size(); i++) {
    		Map<String, WebSocket> clien = clients.get(i);
    		for (WebSocket item : clien.values()) { 
                item.session.getAsyncRemote().sendText(message); 
            }
    	}
    } 
   
    public static synchronized int getOnlineCount() { 
        return onlineCount; 
    } 
   
    public static synchronized void addOnlineCount() { 
        WebSocket.onlineCount++; 
    } 
   
    public static synchronized void subOnlineCount() { 
        WebSocket.onlineCount--; 
    } 
   
    public static synchronized Map<String, WebSocket> getLoginMap() { 
        return loginMap; 
    } 
    public static synchronized List<Map<String, WebSocket>> getClients() { 
        return clients; 
    } 
    
}
